/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2020, LomboTech Co.Ltd.
 * Author: lomboswer <lomboswer@lombotech.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 */
#include <linux/of.h>
#include <linux/regmap.h>
#include <mach/msgch_pro.h>
#include "../regulator.h"

/* set voltage  */
#define IP6103_DCDC0_VREG	0x21
#define IP6103_DCDC1_VREG	0x28
#define IP6103_DCDC2_VREG	0x2f
#define IP6103_DCDC3_VREG	0x36
#define IP6103_DCDC0_VREG_MASK	0x7f
#define IP6103_DCDC1_VREG_MASK	0x7e
#define IP6103_DCDC2_VREG_MASK	0x7e
#define IP6103_DCDC3_VREG_MASK	0x7e

/* enable or disable  */
#define IP6103_DCDC0_CTRL	0x20
#define IP6103_DCDC1_CTRL	0x20
#define IP6103_DCDC2_CTRL	0x20
#define IP6103_DCDC3_CTRL	0x20
#define IP6103_DCDC4_CTRL	0x83
#define IP6103_DCDC5_CTRL	0x83
#define IP6103_LDO0_CTRL	0x41
#define IP6103_LDO1_CTRL	0x41
#define IP6103_LDO2_CTRL	0x41
#define IP6103_LDO4_CTRL	0x41
#define IP6103_LDO5_CTRL	0x41
#define IP6103_LDO6_CTRL	0x41

#define IP6103_DCDC0_EN_MASK	1
#define IP6103_DCDC1_EN_MASK	2
#define IP6103_DCDC2_EN_MASK	4
#define IP6103_DCDC3_EN_MASK	8
#define IP6103_DCDC4_EN_MASK	1
#define IP6103_DCDC5_EN_MASK	8
#define IP6103_LDO0_EN_MASK		1
#define IP6103_LDO1_EN_MASK     2
#define IP6103_LDO2_EN_MASK     4
#define IP6103_LDO4_EN_MASK     16
#define IP6103_LDO5_EN_MASK     32
#define IP6103_LDO6_EN_MASK     64

#define IP6103_DCDC0_NUM_VOLTAGES	127
#define IP6103_DCDC1_NUM_VOLTAGES	IP6103_DCDC0_NUM_VOLTAGES
#define IP6103_DCDC2_NUM_VOLTAGES	IP6103_DCDC0_NUM_VOLTAGES
#define IP6103_DCDC3_NUM_VOLTAGES	105

enum {
	IP6103_ID_DCDC0,
	IP6103_ID_DCDC1,
	IP6103_ID_DCDC2,
	IP6103_ID_DCDC3,
	IP6103_ID_DCDC4,
	IP6103_ID_DCDC5,
	IP6103_ID_LDO0,
	IP6103_ID_LDO1,
	IP6103_ID_LDO2,
	IP6103_ID_LDO4,
	IP6103_ID_LDO5,
	IP6103_ID_LDO6,
	IP6103_ID_LDO7,
};

/**
 * static const struct reg_default ip6103_reg_defaults[] = {
 *	{IP6103_DCDC0_VREG, 0},
 *	{IP6103_DCDC1_VREG, 0},
 *	{IP6103_DCDC2_VREG, 0},
 *	{IP6103_DCDC3_VREG, 0},
 *	{0x20, 0},
 *	{0x41, 0},
 *	{0x83, 0},
 *};
 */

struct regulator_desc lombo_regulators[] = {
	PMIC_DCDC_REG("DCDC0", IP6103, DCDC0, "null", 600000, 12500, 0),
	PMIC_DCDC_REG("DCDC1", IP6103, DCDC1, "null", 600000, 12500, 0),
	PMIC_DCDC_REG("DCDC2", IP6103, DCDC2, "null", 600000, 12500, 0),
	PMIC_DCDC_REG("DCDC3", IP6103, DCDC3, "null", 2200000, 12500, 0),

	/* DCDC4-5 only can be disabled or enabled */
	PMIC_LDO_REG("DCDC4", IP6103, DCDC4, "null"),
	PMIC_LDO_REG("DCDC5", IP6103, DCDC5, "null"),

	PMIC_LDO_REG("LDO0", IP6103, LDO0, "null"),
	PMIC_LDO_REG("LDO1", IP6103, LDO1, "null"),
	PMIC_LDO_REG("LDO2", IP6103, LDO2, "null"),
	PMIC_LDO_REG("LDO4", IP6103, LDO4, "null"),
	PMIC_LDO_REG("LDO5", IP6103, LDO5, "null"),
	PMIC_LDO_REG("LDO6", IP6103, LDO6, "null"),

	/* this regulator can set voltage or enable: enabled by LDO6 */
	[IP6103_ID_LDO7] = {
		.name = "LDO7",
		.supply_name = "vcc_ldo6",
		.of_match = of_match_ptr("REG_LDO7"),
		.regulators_node = of_match_ptr("regulators"),
		.ops = &lombo_dummy_regulator_ops,
		.owner = THIS_MODULE,
	},
};

int __get_regulators_count(void)
{
	return ARRAY_SIZE(lombo_regulators);
}

struct regulator_desc *__get_regulator_desc(void)
{
	return lombo_regulators;
}

int __lombo_read_regulator_data(void *context,
	unsigned int reg, unsigned int *val)
{
	int ret;
	msgch_snd_t sb;
	msgch_rcv_t rb;

	sb.snd_buf.bits.type = MSGCH_CMD_REGULATOR;
	sb.snd_buf.bits.st = MSGCH_SUBTYPE_REGULATOR_READ;
	sb.snd_buf.bits.wait = MSGCH_WAIT_FOREVER;
	sb.snd_buf.bits.msg.smsg.ra = (u8)reg;

	ret = lombo_send_msg(&sb, &rb, CHANNAL_MUTEX_INTERFACE);
	if (ret != 0) {
		pr_err("%s: %d, send msg to backend failed\n",
		__func__, __LINE__);
		return -1;
	}

	if (rb.rcv_buf.bits.rsvd0) {
		pr_err("%s: %d, backend driver get data error: %d\n",
		__func__, __LINE__, rb.rcv_buf.bits.rsvd0);
		return -1;
	}

	*val = rb.rcv_buf.bits.msg.smsg.sr;

	return 0;
}

int __lombo_write_regulator_data(void *context,
	unsigned int reg, unsigned int val)
{
	int ret;
	msgch_snd_t sb;
	msgch_rcv_t rb;

	sb.snd_buf.bits.type = MSGCH_CMD_REGULATOR;
	sb.snd_buf.bits.st = MSGCH_SUBTYPE_REGULATOR_WRITE;
	sb.snd_buf.bits.wait = MSGCH_WAIT_FOREVER;

	sb.snd_buf.bits.msg.smsg.ra = (u8)reg;

	sb.snd_buf.bits.msg.smsg.sr = (u8)val;

	ret = lombo_send_msg(&sb, &rb, CHANNAL_MUTEX_INTERFACE);
	if (ret != 0) {
		pr_err("%s: %d, send msg to backend failed\n",
		__func__, __LINE__);
		return -1;
	}

	if (rb.rcv_buf.bits.rsvd0) {
		pr_err("%s: %d, backend driver set data error\n",
		__func__, __LINE__);
		return -1;
	}

	return 0;
}

struct regmap_config pmic_regmap = {
	.name = "ip6103",
	.reg_bits = 8,
	.val_bits = 8,
	.reg_read = __lombo_read_regulator_data,
	.reg_write = __lombo_write_regulator_data,
	.max_register = 0x83,
	.cache_type = REGCACHE_RBTREE,
/*	.reg_defaults = ip6103_reg_defaults, */
/*	.num_reg_defaults = ARRAY_SIZE(ip6103_reg_defaults), */
};
